package com.whut.monitor.util;


import sun.security.ssl.Debug;

import java.io.*;
import java.util.Vector;

/**
 * Created by Administrator on 2017-11-09.
 */

public class LinearUtil {

    private Vector<Double> X;
    private Vector<Double> Y;
    private double averageX=0;
    private double averageY=0;
    private double Lxx, Lxy, Lyy=0;
    private double r, a, b=0;
    /* 线性回归模型步骤
    *1.求∑x，∑xx，∑y，∑yy，∑xy。
    *2.计算Lxx，Lyy，Lxy
    *  Lxx=∑(x-xˇ)(x-xˇ)
    *  Lyy=∑(y-yˇ)(y-yˇ)
    *  Lxy=∑(x-xˇ)(y-yˇ)
    *3.求 相关系数，并检验；
    *  r = Lxy /( Lxx Lyy)1/2
    *4. 求 回归系数b和 常数a；

    *  b=Lxy /Lxx
    *  a=y - bx
    *5. 列回归方程。
    *6.根据回归方程计算预测值
    */
    public LinearUtil()
    {
        X=new Vector<Double>();
        Y=new Vector<Double>();
    }
    /**从文件中加载自变量X和因变量Y
     * 文件为n行2列的形式，第一列是自变量X，第二列是因变量Y，列之间用','隔开
     * @param filepath 文件路径
     * return 加载结果
     *eg: 123,12
     *    456,67
     *    122,11.2
     *    ...
    */
    public boolean loadXY(String filepath)
    {
        try {
            FileReader fileReader=new FileReader(filepath);
            BufferedReader bufferedReader;
            bufferedReader = new BufferedReader(fileReader);
            String line=null;
            Vector<Double> cell=new Vector<Double>();
            while ((line=bufferedReader.readLine())!=null)
            {
                spilit(line,',',cell);
                if(cell.size()!=2)
                {
                    X.clear();
                    Y.clear();
                    return false;
                }
                X.addElement(cell.elementAt(0));
                Y.addElement(cell.elementAt(1));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  true;
    }
    /** 加载回归模型的自变量和因变量
    * @param strX
    * @param strY
    * return
    */
    public boolean loadXY(String strX, String strY)
    {
        spilit(strX, ',', X);
        spilit(strY, ',', Y);
        if (X.size() != Y.size())
        {
            X.clear();
            Y.clear();
            return false;
        }
        return true;
    }
    public Parameter trainPara(Parameter para)
    {
        averageX = getAverage(X);
        averageY = getAverage(Y);
        Lxx = getLxx();
        Lxy = getLxy();
        Lyy = getLyy();
        para.r=r = getR();
        para.b=b = getB();
        para.a=a = getA();
        return para;
    }
    public String forecast(String x)
    {
         Double y = a+b*Double.valueOf(x);
         return y.toString();
    }
    public void forecast(String xStream,char c,Vector<Double> yCell)
    {
        Vector<Double> cell=new Vector<Double>();
        spilit(xStream,c,cell);
        for(Double x:cell)
        {
            Double y=a+b*Double.valueOf(x);
            yCell.addElement(y);
        }
    }
    public String forecast(String xStream,char c)
    {
        String str=new String();
        Vector<Double> cell=new Vector<Double>();
        spilit(xStream,c,cell);
        for(Double x:cell)
        {
            Double y=a+b*Double.valueOf(x);
            str+=(y+",");
        }
        int end = str.length()-2;
        return str.substring(0,end);
    }
    public String disPlay()
    {
        String str="线性回归方程:Y="+a+"+X*"+b;
        str+=("相关性系数:r="+r);
        return str;
    }



    private double getAverage(Vector<Double> v)
    {
        double ave=0;
        for (int i = 0; i != v.size(); ++i)
        {
            ave += v.elementAt(i);
        }
        return ave / v.size();
    }
    private double getLxx()
    {
        double Lxx=0;
        for (int i = 0; i != X.size(); ++i)
        {
            Lxx += (X.elementAt(i) - averageX)*(X.elementAt(i) - averageX);
        }
        return Lxx;
    }
    private double getLyy()
    {
        double Lyy=0;
        for (int i = 0; i != Y.size(); ++i)
        {
            Lyy += (Y.elementAt(i) - averageY)*(Y.elementAt(i) - averageY);
        }
        return Lyy;
    }
    private double getLxy()
    {
        double Lxy=0;
        for (int i = 0; i != X.size() && i != Y.size(); ++i)
        {
            Lxy += (X.elementAt(i) - averageX)*(Y.elementAt(i) - averageY);
        }
        return Lxy;
    }
    private double getR()
    {
        return r = Lxy / Math.sqrt(Lxx*Lyy);
    }
    private double getB()
    {
        return b = Lxy / Lxx;
    }
    private double getA()
    {
        return a = averageY - averageX*b;
    }
    private void spilit(String stream, char c, Vector<Double> cell)
    {
        int pos = 0;
        while (true)
        {
            pos = stream.indexOf(c);
            if (pos == -1)
            {
                cell.addElement(Double.valueOf(stream));
                return;
            }
            else
            {
                cell.addElement(Double.valueOf(stream.substring(0, pos)));
                stream = stream.substring(pos + 1);
            }
        }
    }
}

class Parameter
{
    public double r;//线性相关系数
    public double a;//回归方程的常数项
    public double b;//回归方程的系数
    Parameter()
    {
        r=0;
        a=0;
        b=0;
    }
}
